
"use strict";

import * as serialport from 'serialport';
import * as q from 'q';
import {EventEmitter} from 'events';

/** COM的基础类,不要直接创建 */
class BaseCom extends EventEmitter {
    constructor(portName?: string) {
        super();
        portName = portName || "COM1";
        // 初始化时直接打开串口
        this.port = new serialport.SerialPort(portName);
        this.port.on('error', function(err) {//处理错误
            console.log(err);
        });
        this.port.on('data', data=> {
            if (!data || data.length === 0) return;
            if (this._defer.promise.isFulfilled()) return; //如果已经完成了,就不再继续后续操作了,不一定需要这句话,但是保险起见还是加上
            let buffer = (data instanceof Buffer) ? data : new Buffer(data.toString());//要转换成buffer操作
            this._tempBuffer = Buffer.concat([this._tempBuffer, buffer], this._tempBuffer.length + buffer.length);
            if (this._dataComplete && this._dataComplete()) {
                this._timeoutId && clearTimeout(this._timeoutId);  //非常重要,不要忘记在这里取消超时设置
                this._proccessData && this._proccessData();//处理数据
            }
        });
    }
    
    /**
    * 调用的serialport串口
    */
    public port: serialport.SerialPort;
    
    /**
    * 用来储存超时进程的timeout object
    */
    protected _timeoutId: NodeJS.Timer = null;
    
    /**
    * 内部defer对象,用来指示测量操作是否完成(超时也算完成)
    */
    protected _defer: q.Deferred<any>;

    /**
    * 用来缓存每个测量操作的buffer
    */
    protected _tempBuffer: Buffer;    
    
    
    /**
    * 设置测量超时
    * @param {number} timeout - 超时的时间,默认为5秒
    */
    protected _surveyTimeout(timeout?: number) {
        timeout = timeout || 5000;
        this._timeoutId = setTimeout(() => {
            //5秒后超时,defer resolve,设置测量状态结束
            this._defer.resolve(null);
        }, timeout);
    }

    /** 
     * 重要
     * 用来判断是否完成本次data读取,具体在子类中实现 
     */
    protected _dataComplete: () => boolean;
    
    /** 
     * 重要
     * 用来处理和解析本次数据,返回需要的结果,具体在子类中实现
     */
    protected _proccessData: () => void;
    
    /** 
    * 执行在测量前,初始化一些状态和变量
    */
    protected _preSurvey(): void {
        this._defer = q.defer();//初始化defer,状态为未完成
        this._tempBuffer = new Buffer(0);//一开始什么数据都没,长度为0
    }
        
    /** 关闭串口 */
    public close(): void {
        this.port.isOpen() && this.port.close();
    }
    
    /** 打开串口 */
    public open(): void {
        this.port.open();
    }
}

export {BaseCom};